package com.hunk.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import com.hunk.utils.io.Print;

/** 
 * Description:
 * 	Date Utility
 * 	Thread safe
 * File:
 * 	DateUtils.java
 * @author HunkDeng
 * @version 1.0
 * @category Utility
 * @since 2012
 */
public class DateUtils {
	public final static String yyyy = "yyyy";
	public final static String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
	public final static String yyyy_MM_dd_HH_mm = "yyyy-MM-dd HH:mm";
	public final static String yyyy_MM_dd = "yyyy-MM-dd";
	public final static String EEE_MMM_dd_HH_mm_ss_zzz_yyyy = "EEE MMM dd HH:mm:ss zzz yyyy";
	public final static String EEE_MMM_dd_HH_mm_ss_zzz0800_yyyy = "EEE MMM dd HH:mm:ss zzz+0800 yyyy";
	
	/** get a new GregorianCalendar instance
	 * @return
	 */
	public static Calendar getCalendar() {
		return new GregorianCalendar();
	} 	
	/**
	 * 为每一个线程提供一个独立的SimpleDateFormat,节省资源
	 * 如果不是重复利用的话其性能未必要，因为每次依然是new，只是说在某线程多次访问此实例的时候性能才会提升。
	 * 同时我们也发现了一个线程并发的实现方式。 
	 */
	private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>() {
		protected  SimpleDateFormat initialValue() {
			return new SimpleDateFormat();
		}
	};	
	/**获取SimpleDateFormat实例
	 * @param format
	 * @return
	 */
	public static DateFormat getDateFormat(String format) {
		SimpleDateFormat sdf = threadLocal.get();
		sdf.applyPattern(format);
		return sdf;
	}	
	/**String convert to date according the format String
	 * @param string
	 * @param format
	 * @return
	 */
	public static Date parseSringToDate(String string, String format) {
		Date date = new Date();
		DateFormat strToDate = getDateFormat(format);
		try {
			date = strToDate.parse(string);
		} catch (ParseException e) {
			e.printStackTrace();
		} 
		return date;
	}			
	/**获得当前年份
	 * @return
	 */
	public static int getCurrentYear() {
		return getCalendar().get(Calendar.YEAR);
	}	
    /**
     * @param date
     * @return
     */
    public static java.sql.Date toSQLDate(Date date) {
        return new java.sql.Date(date.getTime());
    }
    
	/**String convert to date according the format String
	 * @param string
	 * @param format
	 * @param timezone
	 * @return
	 */
	public static Date parseSringToDate(String string, String format, TimeZone timezone) {
		Date date = new Date();
		DateFormat strToDate = getDateFormat(format);
		strToDate.setTimeZone(timezone);
		try {
			date = strToDate.parse(string);
		} catch (ParseException e) {
			throw new RuntimeException("there is a error in parseing :" + string + "to date");
		} 
		return date;
	}
	/**String convert to date according the format String and local time zone
	 * @param string
	 * @param style
	 * @param locale
	 * @return
	 */
	public static Date parseSringToDate(String string, int style, Locale locale) {
		Date date = new Date();
		DateFormat strToDate = DateFormat.getDateInstance(style, locale);
		try {
			date = strToDate.parse(string);
		} catch (ParseException e) {
			throw new RuntimeException("there is a error in parseing :" + string + "to date");
		} 
		return date;
	}
	/**Date convert to string according the format String
	 * @param date
	 * @param format
	 * @return
	 */
	public static String parseDateToString(Date date, String format) {
		DateFormat dateToStr = getDateFormat(format);
		return dateToStr.format(date);
	}
	/**Date convert to string according the format String
	 * @param date
	 * @param format
	 * @param zone
	 * @return
	 */
	public static String parseDateToString(Date date, String format, TimeZone zone) {
		DateFormat dateToStr = getDateFormat(format);
		dateToStr.setTimeZone(zone);
		return dateToStr.format(date);
	}
	/**Date convert to string according the format String
	 * @param date
	 * @param style
	 * @param locale
	 * @return
	 */
	public static String parseDateToString(Date date, int style, Locale locale) {
		DateFormat dateToStr = DateFormat.getDateInstance(style, locale);
		return dateToStr.format(date);
	}	
	/** Return Begin date and End date on current year
	 * @return
	 * 		map with only two key {"startTime","endTime"}
	 */
	public static Map<String, Date> getCurrentYearBeginAndEnd() {
		Map<String, Date> rtn = new HashMap<String, Date>();
		Calendar c = new GregorianCalendar();
		c.set(Calendar.MONTH, 0);
		c.set(Calendar.DAY_OF_MONTH, 1);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		rtn.put("startTime", c.getTime());
		
		c.add(Calendar.YEAR, 1);
		c.add(Calendar.SECOND, -1);
		rtn.put("endTime", c.getTime());
		return rtn;
	}
	/** Return Begin date and End date on current month  
	 * @return
	 * 		map with only two key {"startTime","endTime"}
	 */
	public static Map<String, Date> getCurrentMonthBeginAndEnd() {
		Map<String, Date> rtn = new HashMap<String, Date>();
		Calendar c = new GregorianCalendar();
		c.set(Calendar.DAY_OF_MONTH, 1);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		rtn.put("startTime", c.getTime());
		
		c.add(Calendar.MONTH, 1);
		c.add(Calendar.SECOND, -1);
		rtn.put("endTime", c.getTime());
		return rtn;
	}	
	/**如果今天小于周五，则获取周一和周五零点两个日期
	 * 如果不是，则获取上周的周一和周五零点两个日期
	 * 减去几周
	 * @deprecated
	 * @param week
	 * 			add(Calendar.WEEK_OF_YEAR,week)
	 * @return
	 */
	public static Map<String, Date> getLastWeekBeginAndEnd(int week) {
		Map<String,Date> lastweek = getLastWeekBeginAndEnd();
		Date startTime = lastweek.get("startTime");
		Date endTime = lastweek.get("endTime");
		
		Calendar _startTime = new GregorianCalendar();
		_startTime.setTime(startTime);
		
		Calendar _endTime = new GregorianCalendar();
		_endTime.setTime(endTime);
		
		_startTime.add(Calendar.WEEK_OF_YEAR, week);
		_endTime.add(Calendar.WEEK_OF_YEAR, week);
		
		lastweek.put("startTime", _startTime.getTime());
		lastweek.put("endTime", _endTime.getTime());
		return lastweek;
	}	
	/**如果今天小于周五，则获取周一和周五零点两个日期
	 * 如果不是，则获取上周的周一和周五零点两个日期
	 * @param week
	 * 			再以上基础上再推前几周
	 * @return
	 */
	public static Map<String, Date> getLastWeekBeginAndEnd2(int week) {
		Map<String, Date> rtn = new HashMap<String, Date>();
		
		Date startTime = null;
		Date endTime = null;
		
		Calendar c = getCalendar();
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.add(Calendar.WEEK_OF_YEAR, week);
		
		c.set(Calendar.DAY_OF_WEEK, 4);
		
		if (6 > c.get(Calendar.DAY_OF_WEEK)) {	// 如果是周五以前那减去一周
			c.add(Calendar.WEEK_OF_MONTH, -1);
		} 
		
		c.set(Calendar.DAY_OF_WEEK, 6);
		endTime = c.getTime();
		c.set(Calendar.DAY_OF_WEEK, 2);
		startTime = c.getTime();
		
		
		rtn.put("startTime", startTime);
		rtn.put("endTime", endTime);
		return rtn;
	}	
	/** 如果今天小于周五，则获取周一和周五零点两个日期
	 *  如果不是，则获取上周的周一和周五零点两个日期
	 * @return
	 */
	public static Map<String, Date> getLastWeekBeginAndEnd() {
		Map<String, Date> rtn = new HashMap<String, Date>();
		
		Date startTime = null;
		Date endTime = null;
		
		Calendar c = getCalendar();
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		
		if (6 > c.get(Calendar.DAY_OF_WEEK)) {	// 如果是周五以前那减去一周
			c.add(Calendar.WEEK_OF_MONTH, -1);
		} 
		
		c.set(Calendar.DAY_OF_WEEK, 6);
		endTime = c.getTime();
		c.set(Calendar.DAY_OF_WEEK, 2);
		startTime = c.getTime();
		
		
		rtn.put("startTime", startTime);
		rtn.put("endTime", endTime);
		return rtn;
	}
	
	@SuppressWarnings("unused")
	private static class TestDateUtils {
		public static void main(String[] args) {
			
//			Date date2 = parseSringToDate("Sun Jan 1 00:00:00 UTC+0800 2011", "EEE MMM dd HH:mm:ss zzz+0800 yyyy", Locale.US);
//			Print.println(parseDateToString(date2, yyyy_MM_dd_HH_mm_ss));
			for(int i = 0 ; i <= 12 ; i++) {
				Map<String,Date> lastweek = getLastWeekBeginAndEnd2(0-i);
				Date startTime = lastweek.get("startTime");
				Date endTime = lastweek.get("endTime");
				Print.println(parseDateToString(startTime, yyyy_MM_dd_HH_mm_ss));
				Print.println(parseDateToString(endTime, yyyy_MM_dd_HH_mm_ss));
				Print.println("--------------");
			}
		}
	}
}
